using System.Linq.Expressions;
using DealerPlatform.Core.Core;
using DealerPlatform.Domain.GlobalDto;
using Microsoft.EntityFrameworkCore;

namespace DealerPlatform.Core.Repository
{
    public interface IMyRepository<TEntity> where TEntity : class
    {
        TEntity Delete(TEntity entity);
        Task<TEntity> DeleteAsync(TEntity entity);
        Task<TEntity> GetAsync(Expression<Func<TEntity, bool>> func);
        Task<List<TEntity>> GetListAsync(Expression<Func<TEntity, bool>> func);
        Task<List<TEntity>> GetListAsync(Expression<Func<TEntity, bool>> func, PageWithSortDto dto);
        IQueryable<TEntity> GetQueryable();
        TEntity Insert(TEntity entity);
        Task<TEntity> InsertAsync(TEntity entity);
        TEntity Update(TEntity entity);
        Task<TEntity> UpdateAsync(TEntity entity);
    }

    public class MyRepository<TEntity> : IMyRepository<TEntity> where TEntity : class
    {
        public MyRepository(DealerPlatformContext context)
        {
            _context = context;
        }

        public DealerPlatformContext _context { get; }



        public async Task<List<TEntity>> GetListAsync(Expression<Func<TEntity, bool>> func)
        {
            return await _context.Set<TEntity>().Where(func).ToListAsync();    //正式版
        }

        public async Task<List<TEntity>> GetListAsync(Expression<Func<TEntity, bool>> func, PageWithSortDto dto)
        {
            int skip = (dto.PageIndex - 1) * dto.PageSize;
            if (dto.OrderType == OrderType.Asc)
                return await _context.Set<TEntity>().Where(func).OrderByField(dto.Sort).Skip(skip).Take(dto.PageSize).ToListAsync();    //正式版
            else
                return await _context.Set<TEntity>().Where(func).OrderByField(dto.Sort, false).Skip(skip).Take(dto.PageSize).ToListAsync();    //正式版
        }

        public IQueryable<TEntity> GetQueryable()
        {
            return _context.Set<TEntity>();
        }



        public async Task<TEntity> GetAsync(Expression<Func<TEntity, bool>> func)
        {
            return await _context.Set<TEntity>().FirstOrDefaultAsync(func);
        }


        public TEntity Insert(TEntity entity)
        {
            var res = _context.Set<TEntity>().Add(entity).Entity;
            _context.SaveChanges();
            return res;
        }

        public async Task<TEntity> InsertAsync(TEntity entity)
        {
            var res = (await _context.Set<TEntity>().AddAsync(entity)).Entity;
            _context.SaveChanges();
            return res;
        }


        public TEntity Delete(TEntity entity)
        {
            var res = _context.Set<TEntity>().Remove(entity).Entity;
            _context.SaveChanges();
            return res;
        }

        public async Task<TEntity> DeleteAsync(TEntity entity)
        {
            var res = _context.Set<TEntity>().Remove(entity).Entity;
            await _context.SaveChangesAsync();
            return res;
        }


        public TEntity Update(TEntity entity)
        {
            var res = _context.Set<TEntity>().Update(entity).Entity;
            _context.SaveChanges();
            return res;
        }

        public async Task<TEntity> UpdateAsync(TEntity entity)
        {
            var res = _context.Set<TEntity>().Update(entity).Entity;
            await _context.SaveChangesAsync();
            return res;
        }
    }
}